﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Xml;
using System.IO;
using RsaRegister.Model;

namespace RsaRegister
{
    public enum eAuthStatus { Succeed, Fail, Expired, Guest, LessThanOneWeek,OutOfUsers };
    
    public class RsaClient
    {
       
        RSACryptoServiceProvider rsa;
        public RsaClient()
        {
            rsa = new RSACryptoServiceProvider();
        }
        public RsaClient(string publicKey)
        {
            rsa = new RSACryptoServiceProvider();
            rsa.FromXmlString(publicKey);
        }
        public RsaClient( RSACryptoServiceProvider rsaServiceProvider)
        {                        
            rsa = rsaServiceProvider;
        }
        
        public void SetPubKey(string pubkey)
        {            
            rsa.FromXmlString(pubkey);
        }
        
        public Boolean VerifyRegisterCode(string rcode, string userString)
        {
            RSAPKCS1SignatureDeformatter f = new RSAPKCS1SignatureDeformatter(rsa);
            f.SetHashAlgorithm("SHA1");
            byte[] key = Convert.FromBase64String(rcode);
            SHA1Managed sha = new SHA1Managed();
            byte[] name = sha.ComputeHash(ASCIIEncoding.ASCII.GetBytes(userString));
            return f.VerifySignature(name, key);
        }
        
        public bool VerifyRegisterCode(string rcode, RegInfo regInfo)
        {
            string userString = regInfo.GenerateRegString();
            return VerifyRegisterCode(rcode, userString);
        }
        /// <summary>
        /// 包含软件的信息的授权检查
        /// </summary>
        /// <param name="licFile"></param>
        /// <param name="softId">软件ID</param>
        /// <param name="users">用户数限定时输入已注册用户数。若不限定，保持为0</param>
        /// <returns></returns>
        public eAuthStatus AuthorizeCheck(string licFile,Guid softId,int users=0)
        {
            var regInfo = GetRegInfoFromLicFile(licFile, out string regCode);
            if (regInfo.SoftId != softId) return eAuthStatus.Fail;
            return AuthorizeCheck(licFile,users);
        }

        /// <summary>
        /// 检查授权文件
        /// </summary>
        /// <param name="licFile">授权文件</param>
        /// <param name="users">用户数限定时输入已注册用户数。若不限定，保持为0</param>
        /// <returns>eAuthStatus枚举</returns>
        public eAuthStatus AuthorizeCheck(string licFile,int users=0)
        {
            eAuthStatus a = eAuthStatus.Succeed;
            if (!File.Exists(licFile)) a = eAuthStatus.Fail;
            else
            {
                try
                {
                    RegInfo regInfo = GetRegInfoFromLicFile(licFile, out string rcode);                   
                    if (VerifyRegisterCode(rcode, regInfo))
                    {
                        if (regInfo.ExpireDate.Year > 1)//设置了时效
                        {
                            if (DateTime.Now > regInfo.ExpireDate) a = eAuthStatus.Expired; //超期    
                            else if ((regInfo.ExpireDate - DateTime.Now).Days <= 7) a = eAuthStatus.LessThanOneWeek;
                        }
                        if(users>0)//用户数限定
                        {
                            if(regInfo.TotalUsers<users)
                            {
                                a = eAuthStatus.OutOfUsers;
                            }
                        }
                        if (regInfo.User == "000000") a = eAuthStatus.Guest;//测试账户                         
                    }
                    else a = eAuthStatus.Fail;
                }
                catch
                {
                    a = eAuthStatus.Fail;
                }
            }
            return a;
        }

        public RegInfo GetRegInfoFromLicFile(string licFile,out string regsterCode)
        {
            RegInfo regInfo = new RegInfo();
            var props = typeof(RegInfo).GetProperties();
            regsterCode = "";
            if (!File.Exists(licFile)) return null;//文件不存在
            XmlDocument doc = new XmlDocument();
            doc.Load(licFile);
            XmlElement root = doc.DocumentElement;
            if (!root.HasChildNodes) return null;//空注册文件
            XmlNode node = root.SelectSingleNode("RegisterCode");
            if (node == null) return null;//非法注册文件
            regsterCode = node.InnerText;
            foreach (var p in props)
            {
                node = root.SelectSingleNode(p.Name);
                if(node!=null)
                {
                    if (!string.IsNullOrEmpty(node.InnerText))
                    {
                        if (p.PropertyType.IsEnum)
                        {
                            var val = Enum.Parse(p.PropertyType, node.InnerText);
                            p.SetValue(regInfo, val, null);
                        }
                        else if (p.PropertyType==typeof( System.DateTime))
                        {
                            DateTime value = Convert.ToDateTime(node.InnerText);
                            p.SetValue(regInfo, value, null);
                        }
                        else if (p.PropertyType == typeof(System.Int32))
                        {
                            Int32 value = Convert.ToInt32(node.InnerText);
                            p.SetValue(regInfo, value, null);
                        }
                        else if(p.PropertyType==typeof(Guid))
                        {
                            if(Guid.TryParse(node.InnerText,out Guid guid))
                            {
                                p.SetValue(regInfo, guid, null);
                            }
                        }
                        else
                        {
                            p.SetValue(regInfo, node.InnerText, null);
                        }
                    }
                }               
            }
            return regInfo;           

        }

       

        //public string GetUserFromLicenseFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    string user = "";
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "User")
        //                user = reader.ReadElementContentAsString();
        //        }
        //    }
        //    reader.Close();
        //    return user;
        //}
        ///// <summary>
        ///// 获取授权用户数。
        ///// </summary>
        ///// <param name="fullname"></param>
        ///// <returns>失败返回0</returns>
        //public int GetTotalusersFromLicFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    int totalu = 0;
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "TotalUsers")
        //                totalu = reader.ReadElementContentAsInt();
        //        }
        //    }
        //    reader.Close();
        //    return totalu;
        //}
        //public string GetGuidFromLicFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    string guid = "";
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "GUID")
        //                 guid = reader.ReadElementContentAsString();
        //        }
        //    }
        //    reader.Close();
        //    return guid;
        //}

        //public string GetCpuidFromLicFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    string cpuid = "";
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "CPUID")
        //                cpuid = reader.ReadElementContentAsString();
        //        }
        //    }
        //    reader.Close();
        //    return cpuid;
        //}
        ///// <summary>
        ///// 从license文件中获取有效期
        ///// </summary>
        ///// <param name="fullname"></param>
        ///// <returns>成功返回有效期，失败返回DateTime.MinValue</returns>
        //public DateTime GetExpiredateFromLicenseFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    DateTime exd = DateTime.MinValue;
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "ExpireDate")
        //                exd =DateTime.Parse( reader.ReadElementContentAsString());
        //        }
        //    }
        //    reader.Close();
        //    return exd;
        //}
        //public string GetRegisterCodeFromLicenseFile(string fullname)
        //{
        //    XmlTextReader reader = new XmlTextReader(fullname);
        //    string rcode = "";
        //    while (reader.Read())
        //    {
        //        if (reader.NodeType == XmlNodeType.Element)
        //        {
        //            if (reader.Name == "RegisterCode")
        //                rcode = reader.ReadElementContentAsString();
        //        }
        //    }
        //    reader.Close();
        //    return rcode;
        //}
        #region RSA加密
        //RSA的加密函数  string
        public string RSAEncrypt( string m_strEncryptString)
        {

            byte[] PlainTextBArray;
            byte[] CypherTextBArray;
            string Result;           
                   
            PlainTextBArray = (new UnicodeEncoding()).GetBytes(m_strEncryptString);
            CypherTextBArray = rsa.Encrypt(PlainTextBArray, false);
            Result = Convert.ToBase64String(CypherTextBArray);
            return Result;
        }
        //RSA的加密函数 byte[]
        public string RSAEncrypt( byte[] EncryptString)
        {
            byte[] CypherTextBArray;
            string Result;
            
            CypherTextBArray = rsa.Encrypt(EncryptString, false);
            Result = Convert.ToBase64String(CypherTextBArray);
            return Result;
        }
        #endregion
        #region RSA 签名验证
        /// <summary>
        /// 签名验证
        /// </summary>
        /// <param name="p_strHashbyteDeformatter">待验证的用户名</param>
        /// <param name="p_strDeformatterData">注册码</param>
        /// <returns></returns>
        public bool SignatureDeformatter( string p_strHashbyteDeformatter, string p_strDeformatterData)
        {
            try
            {
                byte[] rgbHash = Convert.FromBase64String(p_strHashbyteDeformatter);
                
                RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(rsa);
                deformatter.SetHashAlgorithm("MD5");
                byte[] rgbSignature = Convert.FromBase64String(p_strDeformatterData);
                if (deformatter.VerifySignature(rgbHash, rgbSignature))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }
        #endregion
    }
}
